package main

import (
	"fmt"

	"gitee.com/wmdng/lua"
)

var (
	sfh *Sflash
)

func lversion(l *lua.State) int {
	l.Push(gjk.GetVersion())
	return 1
}

func ldevice(l *lua.State) int {
	l.Push(gjk.GetDevice())
	return 1
}

func lregname(l *lua.State) int {
	v := l.ToInteger(1)
	l.Push(gjk.GetRegName(uint32(v)))
	return 1
}

func lhalt(l *lua.State) int {
	gjk.Halt()
	return 0
}

func lgointdis(l *lua.State) int {
	gjk.GoIntDis()
	return 0
}

func lstep(l *lua.State) int {
	gjk.Step()
	return 0
}

func lreadreg(l *lua.State) int {
	v := l.ToInteger(1)
	l.Push(gjk.ReadReg(uint32(v)))
	return 1
}

func lwritereg(l *lua.State) int {
	addr := l.ToInteger(1)
	data := l.ToInteger(2)
	gjk.WriteReg(uint32(addr), uint32(data))
	return 0
}

// 1 : addr
// 2 : string
func lwritemem(l *lua.State) int {
	addr := l.ToInteger(1)
	data := l.ToString(2)
	gjk.WriteMem(uint32(addr), []byte(data))
	return 0
}

// 1 : addr
// 2 : tlen
// ret : string
func lreadmem(l *lua.State) int {
	addr := l.ToInteger(1)
	tlen := l.ToInteger(2)
	data := gjk.ReadMem(uint32(addr), uint32(tlen))
	l.Push(string(data))
	return 1
}

func sfc_probe(l *lua.State) int {
	var err error
	sfh, err = NewFlash()
	if err != nil {
		fmt.Println("probe, ", err)
	}
	return 0
}

// 1 : addr
// 2 : tlen
// ret : string
func sfc_read(l *lua.State) int {
	addr := l.ToInteger(1)
	tlen := l.ToInteger(2)
	p := make([]byte, tlen)
	n, err := sfh.ReadAt(p[:], int64(addr))
	if err != nil {
		fmt.Println("sf, readat, ", err)
		return 0
	}

	fmt.Println("readat, ret = ", n)
	if n != int(tlen) {
		fmt.Println("readat, len not eq")
		return 0
	}

	/**/
	l.Push(string(p[:]))
	return 1
}

// 1 : addr
// 2 : string
func sfc_write(l *lua.State) int {
	addr := l.ToInteger(1)
	strs := l.ToString(2)
	data := []byte(strs)
	n, err := sfh.WriteAt(data, int64(addr))

	if err != nil {
		fmt.Println("sf, writeat, ", err)
		return 0
	}

	fmt.Println("writeat, ret = ", n)
	if n != len(data) {
		fmt.Println("writeat, len not eq")
		return 0
	}

	return 0
}

func addFunc(l *lua.State, nm string, fn func(l *lua.State) int) {
	l.Push(nm)
	l.Push(fn)
	l.SetTableRaw(-3)
	return
}

func Open(l *lua.State) int {

	l.NewTable(0, 16)
	addFunc(l, "Version", lversion)
	addFunc(l, "Device", ldevice)
	addFunc(l, "RegName", lregname)
	addFunc(l, "Halt", lhalt)
	addFunc(l, "Go", lgointdis)
	addFunc(l, "Step", lstep)
	addFunc(l, "ReadReg", lreadreg)
	addFunc(l, "WriteReg", lwritereg)
	addFunc(l, "ReadMem", lreadmem)
	addFunc(l, "WriteMem", lwritemem)
	addFunc(l, "sfcProbe", sfc_probe)
	addFunc(l, "sfcRead", sfc_read)
	addFunc(l, "sfcWrite", sfc_write)

	// MetaTable
	l.NewTable(0, 2)

	l.Push("__index")
	l.Push(lindex)
	l.SetTableRaw(-3)

	l.Push("__newindex")
	l.Push(lnewindex)
	l.SetTableRaw(-3)

	l.SetMetaTable(-2)
	return 1
}

func lindex(l *lua.State) int {
	switch l.ToString(2) {
	case "temp":
		l.Push(1234)
	default:
		l.Push(nil)
	}
	return 1
}

func lnewindex(l *lua.State) int {
	switch key := l.ToString(2); key {
	case "temp":
	default:
		panic("io: invalid field: " + key)
	}
	return 0
}
